home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / vms_src / vmsreaddir.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-07  |  6.4 KB  |  296 lines

  1. /*
  2. **  VMS readdir() routines.
  3. **  Written by Rich $alz, <rsalz@bbn.com> in August, 1990.
  4. **  This code has no copyright.
  5. */
  6.  
  7. /* 12-NOV-1990 added d_namlen field and special case "." name -GJC@MITECH.COM 
  8.  * 31-DEC-1992 modified for use with VMS-FSP 2.6.5jt.2 -S.A.Pechler@bdk.tue.nl
  9.  * 08-FEB-1993 Optimized for use with VMS-FSP 2.6.5jt.3 -S.A.Pechler@bdk.tue.nl
  10.  * 07-MAY-1993 Modified for use with VMS-FSP V2.7.0 -S.A.Pechler@bdk.tue.nl
  11.  */
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #include <errno.h>
  16. #include <descrip.h>
  17. #include <rmsdef.h>
  18. #include "dirent.h"
  19.  
  20.     /* Uncomment the next line to get a test routine. */
  21. /*#define TEST*/
  22.  
  23.     /* Number of elements in vms_versions array */
  24. #define VERSIZE(e)    (sizeof e->vms_versions / sizeof e->vms_versions[0])
  25.  
  26.     /* Linked in later. */
  27. extern char    *malloc();
  28. extern char    *strrchr();
  29. extern char    *strcpy();
  30.  
  31.  
  32. /*
  33. **  Open a directory, return a handle for later use.
  34. */
  35. DIR *
  36. opendir(name)
  37.     char    *name;
  38. {
  39.     DIR        *dd;
  40.  
  41.     /* Get memory for the handle, and the pattern. */
  42.     if ((dd = (DIR *)malloc(sizeof *dd)) == NULL) {
  43.     errno = ENOMEM;
  44.     return NULL;
  45.     }
  46.     
  47.     if (strcmp(".",name) == 0) name = "";
  48.     
  49.     dd->pattern = malloc((unsigned int)(strlen(name) + sizeof "*.*" + 1));
  50.     if (dd->pattern == NULL) {
  51.     free((char *)dd);
  52.     errno = ENOMEM;
  53.     return NULL;
  54.     }
  55.  
  56.     /* Fill in the fields; mainly playing with the descriptor. */
  57.     (void)sprintf(dd->pattern, "%s*.*", name);
  58.     dd->context = 0;
  59.     dd->vms_wantversions = 0;
  60.     dd->pat.dsc$a_pointer = dd->pattern;
  61.     dd->pat.dsc$w_length = strlen(dd->pattern);
  62.     dd->pat.dsc$b_dtype = DSC$K_DTYPE_T;
  63.     dd->pat.dsc$b_class = DSC$K_CLASS_S;
  64.  
  65.     return dd;
  66. }
  67.  
  68.  
  69. /*
  70. **  Set the flag to indicate we want versions or not.
  71. */
  72. void
  73. vmsreaddirversions(dd, flag)
  74.     DIR        *dd;
  75.     int        flag;
  76. {
  77.     dd->vms_wantversions = flag;
  78. }
  79.  
  80.  
  81. /*
  82. **  Free up an opened directory.
  83. */
  84. void
  85. closedir(dd)
  86.     DIR        *dd;
  87. {
  88.     free(dd->pattern);
  89.     free((char *)dd);
  90. }
  91.  
  92.  
  93. /*
  94. **  Collect all the version numbers for the current file.
  95. */
  96. static void
  97. collectversions(dd)
  98.     DIR                *dd;
  99. {
  100.     struct dsc$descriptor_s    pat;
  101.     struct dsc$descriptor_s    res;
  102.     struct dirent        *e;
  103.     char            *p;
  104.     char            buff[sizeof dd->entry.d_name];
  105.     int                i;
  106.     char            *text;
  107.     long            context;
  108.  
  109.     /* Convenient shorthand. */
  110.     e = &dd->entry;
  111.  
  112.     /* Add the version wildcard, ignoring the "*.*" put on before */
  113.     i = strlen(dd->pattern);
  114.     text = malloc((unsigned int)(i + strlen(e->d_name)+ 2 + 1));
  115.     if (text == NULL)
  116.     return;
  117.     (void)strcpy(text, dd->pattern);
  118.     (void)sprintf(&text[i - 3], "%s;*", e->d_name);
  119.  
  120.     /* Set up the pattern descriptor. */
  121.     pat.dsc$a_pointer = text;
  122.     pat.dsc$w_length = strlen(text);
  123.     pat.dsc$b_dtype = DSC$K_DTYPE_T;
  124.     pat.dsc$b_class = DSC$K_CLASS_S;
  125.  
  126.     /* Set up result descriptor. */
  127.     res.dsc$a_pointer = buff;
  128.     res.dsc$w_length = sizeof buff - 2;
  129.     res.dsc$b_dtype = DSC$K_DTYPE_T;
  130.     res.dsc$b_class = DSC$K_CLASS_S;
  131.  
  132.     /* Read files, collecting versions. */
  133.     for (context = 0; e->vms_verscount < VERSIZE(e); e->vms_verscount++) {
  134.     if (lib$find_file(&pat, &res, &context) == RMS$_NMF || context == 0)
  135.         break;
  136.     buff[sizeof buff - 1] = '\0';
  137.     if (p = strchr(buff, ';'))
  138.         e->vms_versions[e->vms_verscount] = atoi(p + 1);
  139.     else
  140.         e->vms_versions[e->vms_verscount] = -1;
  141.     }
  142.  
  143.     free(text);
  144. }
  145.  
  146.  
  147. /*
  148. **  Read the next entry from the directory.
  149. */
  150. struct dirent *
  151. readdir(dd)
  152.     DIR                *dd;
  153. {
  154.     struct dsc$descriptor_s    res;
  155.     char            *p;
  156.     char            buff[sizeof dd->entry.d_name];
  157.     int                i;
  158.  
  159.     /* Set up result descriptor, and get next file. */
  160.     res.dsc$a_pointer = buff;
  161.     res.dsc$w_length = sizeof buff - 2;
  162.     res.dsc$b_dtype = DSC$K_DTYPE_T;
  163.     res.dsc$b_class = DSC$K_CLASS_S;
  164.     if (lib$find_file(&dd->pat, &res, &dd->context) == RMS$_NMF
  165.      || dd->context == 0L)
  166.     /* None left... */
  167.     return NULL;
  168.  
  169.     /* Force the buffer to end with a NUL. */
  170.     buff[sizeof buff - 1] = '\0';
  171.     for (p = buff; !isspace(*p); p++)
  172.     ;
  173.     *p = '\0';
  174.  
  175.     /* Skip any directory component and just copy the name. */
  176.     if (p = strchr(buff, ']'))
  177.     (void)strcpy(dd->entry.d_name, p + 1);
  178.     else
  179.     (void)strcpy(dd->entry.d_name, buff);
  180.  
  181.     /* Clobber the version. */
  182.     if (p = strchr(dd->entry.d_name, ';'))
  183.     *p = '\0';
  184.  
  185.     dd->entry.d_namlen = strlen(dd->entry.d_name);
  186.  
  187.     dd->entry.vms_verscount = 0;
  188.     if (dd->vms_wantversions)
  189.     collectversions(dd);
  190.     return &dd->entry;
  191. }
  192.  
  193.  
  194. /*
  195. **  Return something that can be used in a seekdir later.
  196. */
  197. long
  198. telldir(dd)
  199.     DIR        *dd;
  200. {
  201.     return dd->context;
  202. }
  203.  
  204. /*
  205. ** RMDIR emulation function.
  206. ** Converts the given path to VMS-style, and uses the delete() function
  207. */
  208. #ifndef rmdir
  209. long
  210. rmdir (path)
  211.    char *path;
  212. {
  213.  
  214.   /* change the protection, to enable deletion */
  215.   if (chmod(path,0000700)) return(-1);
  216. #ifdef DEBUG
  217.  printf("rmdir: %s\n",path);
  218. #endif
  219.   return(delete(path));
  220. }
  221. #endif
  222.  
  223. /*
  224. **  Return to a spot where we used to be.
  225. */
  226. void
  227. seekdir(dd, pos)
  228.     DIR        *dd;
  229.     long    pos;
  230. {
  231.     dd->context = pos;
  232. }
  233.  
  234. /*
  235.  * FOPEN emulation function.
  236.  * !! The number of arguments differs from the open-definition in unixio.h,
  237.  * only 2 arguments are allowed here; filename and mode.
  238.  */
  239. int vms_fopen(filespec,a_mode)
  240. const char *filespec,*a_mode;
  241. /*
  242. { return (fopen(filespec,a_mode,"mbf=2","mbc=32","shr=get","mrs=1024",
  243.                 "ctx=rec","rfm=fix")); }
  244. */
  245. {  return (fopen(filespec,a_mode,"mbf=2","mbc=32","shr=get","mrs=1024")); }
  246.  
  247. /*
  248.  * OPEN emulation function.
  249.  * Converts pathname to VMS-style first.
  250.  * !! The number of arguments differs from the open-definition in unixio.h,
  251.  * only 3 arguments are allowed here; filename, flags and mode.
  252.  */
  253. int vms_open(filespec, flags, mode)
  254. char *filespec;
  255. int flags;
  256. unsigned int mode;
  257. { return(open(filespec,flags,mode,"mbf=2","mbc=32")); }
  258.  
  259. #ifdef    TEST
  260. main()
  261. {
  262.     char        buff[256];
  263.     DIR            *dd;
  264.     struct dirent    *dp;
  265.     int            i;
  266.     int            j;
  267.  
  268.     for ( ; ; ) {
  269.     printf("\n\nEnter dir:  ");
  270.     (void)fflush(stdout);
  271.     (void)gets(buff);
  272.     if (buff[0] == '\0')
  273.         break;
  274.     if ((dd = opendir(buff)) == NULL) {
  275.         perror(buff);
  276.         continue;
  277.     }
  278.  
  279.     /* Print the directory contents twice, the second time print
  280.      * the versions. */
  281.     for (i = 0; i < 2; i++) {
  282.         while (dp = readdir(dd)) {
  283.         printf("%s%s", i ? "\t" : "    ", dp->d_name);
  284.         for (j = 0; j < dp->vms_verscount; j++)
  285.             printf("  %d", dp->vms_versions[j]);
  286.         printf("\n");
  287.         }
  288.         rewinddir(dd);
  289.         vmsreaddirversions(dd, 1);
  290.     }
  291.     closedir(dd);
  292.     }
  293.     exit(0);
  294. }
  295. #endif    /* TEST */
  296.